package com.jyw.flowable.service.impl;

import cn.hutool.core.util.StrUtil;
import com.jyw.common.core.page.TableDataInfo;
import com.jyw.flowable.domain.dto.WfDeployPageDto;
import com.jyw.flowable.domain.dto.WfPublishPageDto;
import com.jyw.flowable.domain.vo.WfDeployVo;
import com.jyw.flowable.service.IWfDeployService;
import org.flowable.common.engine.impl.db.SuspensionState;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.repository.Deployment;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.engine.repository.ProcessDefinitionQuery;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author Created by ZhangCheng on 2023/11/14
 */
@Service
public class WfDeployServiceImpl implements IWfDeployService {

    @Resource
    private RepositoryService repositoryService;

    @Override
    public TableDataInfo<WfDeployVo> list(WfDeployPageDto wfDeployPageDto) {
        ProcessDefinitionQuery query = repositoryService.createProcessDefinitionQuery()
                .latestVersion()
                .orderByProcessDefinitionKey()
                .asc();
        // 流程标识
        if (StrUtil.isNotBlank(wfDeployPageDto.getProcessKey())) {
            query.processDefinitionKeyLike("%" + wfDeployPageDto.getProcessKey() + "%");
        }
        // 流程名称
        if (StrUtil.isNotBlank(wfDeployPageDto.getProcessName())) {
            query.processDefinitionNameLike("%" + wfDeployPageDto.getProcessName() + "%");
        }
        // 流程分类
        if (StrUtil.isNotBlank(wfDeployPageDto.getCategory())) {
            query.processDefinitionCategory(wfDeployPageDto.getCategory());
        }
        // 流程状态
        if (StrUtil.isNotBlank(wfDeployPageDto.getState())) {
            if (SuspensionState.ACTIVE.toString().equals(wfDeployPageDto.getState())) {
                query.active();
            } else if (SuspensionState.SUSPENDED.toString().equals(wfDeployPageDto.getState())) {
                query.suspended();
            }
        }
        long pageTotal = query.count();
        if (pageTotal <= 0) {
            return TableDataInfo.build();
        }
        int offset = wfDeployPageDto.getPageSize() * (wfDeployPageDto.getPageNum() - 1);
        List<ProcessDefinition> definitionList = query.listPage(offset,
                wfDeployPageDto.getPageSize());
        List<WfDeployVo> deployVoList = new ArrayList<>(definitionList.size());
        for (ProcessDefinition processDefinition : definitionList) {
            String deploymentId = processDefinition.getDeploymentId();
            Deployment deployment = repositoryService.createDeploymentQuery().deploymentId(deploymentId).singleResult();
            WfDeployVo vo = new WfDeployVo();
            vo.setDefinitionId(processDefinition.getId());
            vo.setProcessKey(processDefinition.getKey());
            vo.setProcessName(processDefinition.getName());
            vo.setVersion(processDefinition.getVersion());
            vo.setCategory(processDefinition.getCategory());
            vo.setDeploymentId(processDefinition.getDeploymentId());
            vo.setSuspended(processDefinition.isSuspended());
            // 流程部署信息
            vo.setCategory(deployment.getCategory());
            vo.setDeploymentTime(deployment.getDeploymentTime());
            deployVoList.add(vo);
        }
        return TableDataInfo.build(deployVoList, pageTotal);
    }

    @Override
    public TableDataInfo<WfDeployVo> queryPublishList(WfPublishPageDto wfPublishPageDto) {
        // 创建查询条件
        ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery()
                .processDefinitionKey(wfPublishPageDto.getProcessKey())
                .orderByProcessDefinitionVersion()
                .desc();
        long pageTotal = processDefinitionQuery.count();
        if (pageTotal <= 0) {
            return TableDataInfo.build();
        }
        // 根据查询条件，查询所有版本
        int offset = wfPublishPageDto.getPageSize() * (wfPublishPageDto.getPageNum() - 1);
        List<ProcessDefinition> processDefinitionList = processDefinitionQuery
                .listPage(offset, wfPublishPageDto.getPageSize());
        List<WfDeployVo> deployVoList = processDefinitionList.stream().map(item -> {
            WfDeployVo vo = new WfDeployVo();
            vo.setDefinitionId(item.getId());
            vo.setProcessKey(item.getKey());
            vo.setProcessName(item.getName());
            vo.setVersion(item.getVersion());
            vo.setCategory(item.getCategory());
            vo.setDeploymentId(item.getDeploymentId());
            vo.setSuspended(item.isSuspended());
            return vo;
        }).collect(Collectors.toList());
        return TableDataInfo.build(deployVoList, pageTotal);
    }

    @Override
    public String queryBpmnXmlById(String definitionId) {
        return null;
    }

    @Override
    public void deleteByIds(String[] ids) {
        Arrays.asList(ids).forEach(deployId -> {
            repositoryService.deleteDeployment(deployId, true);
        });
    }
}
